/*
File:		SapperBot.cpp
Author:		Ben Feldmann and Colby Yeates
Purpose:	Class to manage game SapperBot enemies
*/

#include "SapperBot.h"
#include "SGD Wrappers/CSGD_TextureManager.h"
#include "SGD Wrappers/CSGD_Direct3D.h"
#include "Event.h"
#include "EventSystem.h"
#include "MessageSystem.h"
#include "DestroyEntityMessage.h"
#include "CreatePickUpMessage.h"
#include "GamePlayState.h"
#include "SGD Wrappers\SGD_Math.h"
#include "Tile.h"
#include "Player.h"
#include "SGD Wrappers\CSGD_XAudio2.h"

unsigned int SapperBot::Count = 0;
int SapperBot::SapSound = -1;
int SapperBot::BoltSound = -1;

// Constructor
SapperBot::SapperBot() : Energy(0), Draining(1), x1(0), x2(0), y1(0), y2(0), Waiting(false), OnScreen(false), WaitTimer(0)
{
	SetHealth(250.0f);
	SetDifficulty(7);
	SetX(300);
	SetY(200);
	SetSpeed(20);
	SetWidth(46);
	SetHeight(46);

	int randParts = rand() % 7 + 3;
	SetMetal(randParts);
	SetCircuitry(randParts);

	SetPrevX(GetX()); 
	SetPrevY(GetY());
	SetCollided(false);

	SetTextureID(CSGD_TextureManager::GetInstance()->LoadTexture(_T("Graphics/Sapper.png"),D3DCOLOR_XRGB(0,255,0)));

	EventSystem::GetInstance()->RegisterClient("target_hit", this);

	// Load up the sounds
	if( SapSound == -1 )
		SapSound = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/sap.wav"));
	if( BoltSound == -1 )
		BoltSound = CSGD_XAudio2::GetInstance()->SFXLoadSound(_T("Sound/bolt.wav"));

	++Count;
}

// Destructor
SapperBot::~SapperBot() 
{	
	if(GetTextureID() != -1 )
	{
		CSGD_TextureManager::GetInstance()->UnloadTexture(GetTextureID());
		SetTextureID(-1);
	}

	// Unload the sound
	if( --Count == 0 )
	{
		if( SapSound )
		{
			CSGD_XAudio2::GetInstance()->SFXStopSound(SapSound);
			CSGD_XAudio2::GetInstance()->SFXUnloadSound(SapSound);
			SapSound = -1;
		}
		if( BoltSound )
		{
			CSGD_XAudio2::GetInstance()->SFXStopSound(BoltSound);
			CSGD_XAudio2::GetInstance()->SFXUnloadSound(BoltSound);
			BoltSound = -1;
		}
	}

	EventSystem::GetInstance()->UnregisterClientAll(this);
}

// Update
void SapperBot::Update(float elapsed) 
{

	// Only update if it's on camera
	int camx = GamePlayState::GetInstance()->GetCamX();
	int camy = GamePlayState::GetInstance()->GetCamY();
	if( GetX() > camx + 800 || GetX() + GetWidth() < camx || GetY() + GetHeight() < camy || GetY() > camy + 600 )
	{
		OnScreen = false;
		return;
	}

	Enemy::Update(elapsed);

	OnScreen = true;

	// Die if out of health
	if(GetHealth() <= 0)
	{
		// Drop Scraps
		CreatePickUpMessage* msg1 = new CreatePickUpMessage(0, GetMetal(), GetVectorPos(), GetType());
		MessageSystem::GetInstance()->SendMsg(msg1);
		msg1 = nullptr;

		// Drop Circuits
		CreatePickUpMessage* msg2 = new CreatePickUpMessage(1, GetCircuitry(), GetVectorPos(), GetType());
		MessageSystem::GetInstance()->SendMsg(msg2);
		msg2 = nullptr;

		// Get Dead
		DestroyEntityMessage* msg = new DestroyEntityMessage(this);
		MessageSystem::GetInstance()->SendMsg(msg);
		msg = nullptr;

		return;
	}

	if( disabled )
		return;

	WaitTimer -= elapsed;

	// Collision Handling
	if(GetCollided() == false)
	{
		SetPrevX(GetX());
		SetPrevY(GetY());
	}
	SetCollided(false);

	Player* target = GetPlayer();

	// Update the lightning's points
	x1 = (int)Lerp(GetX(),target->GetX(),0.33f) + rand()%70 - 35;
	y1 = (int)Lerp(GetY(),target->GetY(),0.33f) + rand()%70 - 35;
	x2 = (int)Lerp(GetX(),target->GetX(),0.66f) + rand()%70 - 35;
	y2 = (int)Lerp(GetY(),target->GetY(),0.66f) + rand()%70 - 35;

	// Lightning
	if( WaitTimer <= 0 )
	{
		if( Energy >= 30 )
		{
			target->TakeDam(25);
			Energy = 0;
			CSGD_XAudio2::GetInstance()->SFXPlaySound(BoltSound);
		}
		else if( target->GetEnergy() > 10 )
		{
			target->SetEnergy(target->GetEnergy() - 10);
			Energy += 10;
			CSGD_XAudio2::GetInstance()->SFXPlaySound(SapSound);
		}
		WaitTimer = 3.0f;
	}

	// Determine the direction to move
	int xdist = (int)abs(target->GetX() - GetX());
	int ydist = (int)abs(target->GetY() - GetY());

	// Movement
	if( xdist > ydist )
	{
		if( target->GetX() > GetX() )
		{
			// Close in
			if( target->GetX() > GetX() + 300 )
				SetX(GetX() + GetSpeed() * elapsed);
			// Back up
			if( target->GetX() < GetX() + 150 )
				SetX(GetX() - GetSpeed() * elapsed);
			SetDirection(0);
		}
		else if( target->GetX() < GetX() )
		{
			// Close in
			if( target->GetX() < GetX() - 300 )
				SetX(GetX() - GetSpeed() * elapsed);
			// Back up
			if( target->GetX() > GetX() - 150 )
				SetX(GetX() + GetSpeed() * elapsed);
			SetDirection(1);
		}
	}
	else
	{
		if( target->GetY() > GetY() )
		{
			// Close in
			if( target->GetY() > GetY() + 300 )
				SetY(GetY() + GetSpeed() * elapsed);
			// Back up5
			if( target->GetY() < GetY() + 150 )
				SetY(GetY() - GetSpeed() * elapsed);
			SetDirection(2);
		}
		else if( target->GetY() < GetY() )
		{
			// Close in
			if( target->GetY() < GetY() - 300 )
				SetY(GetY() - GetSpeed() * elapsed);
			// Back up
			if( target->GetY() > GetY() - 150 )
				SetY(GetY() - GetSpeed() * elapsed);
			SetDirection(3);
		}
	}
}

// Draw
void SapperBot::Render() 
{
	if( !OnScreen )
		return;

	if(GetTextureID() != -1)
	{
		RECT r = {0,0,46,46};
		switch( GetDirection() )
		{
		case 0: // Right
			r.top += 92;
			r.bottom += 92;
			break;
		case 1: // Left
			r.top += 46;
			r.bottom += 46;
			break;
		case 3: // Up
			r.top += 138;
			r.bottom += 138;
			break;
		}
		CSGD_TextureManager::GetInstance()->Draw(GetTextureID(), int(GetX()- GamePlayState::GetInstance()->GetCamX()), int(GetY() - GamePlayState::GetInstance()->GetCamY()),1,1,&r);
	}

	RECT collision = {(LONG)(GetX()- GamePlayState::GetInstance()->GetCamX()), (LONG)(GetY() - GamePlayState::GetInstance()->GetCamY()), (LONG)(GetX()- GamePlayState::GetInstance()->GetCamX()) + GetWidth(), (LONG)(GetY() - GamePlayState::GetInstance()->GetCamY()) + GetHeight()};
	//CSGD_Direct3D::GetInstance()->DrawRect(collision,255,255,255);

	LightningBolt();

	Enemy::Render();
}

// Collision
bool SapperBot::CheckCollision(IEntity* base) 
{
	if( !OnScreen )
		return false;

	if(Entity::CheckCollision(base) == true && ( base->GetType() == OBJ_ENEMY || base->GetType() == OBJ_PLAYER || base->GetType() == OBJ_TILE || base->GetType() == OBJ_CHEST) )
	{
		if( base->GetType() == OBJ_TILE )
		{
			if( dynamic_cast<Tile*>(base)->GetTileType() != TILE_COLLISION )
				return false;
		}
		SetX(GetPrevX()); 
		SetY(GetPrevY()); 
		SetCollided(true);
		return true;
	}
	else
	{
		SetCollided(false);
		return false;
	}
}

// Attack
void SapperBot::Attack() 
{

}

// Special Attack
void SapperBot::SpecialAttack() 
{

}

// Event handler for damage
void SapperBot::HandleEvent(Event* thisEvent)
{
	if(thisEvent->GetParameter() != this)
		return;

	if(thisEvent->GetEventID() == "target_hit" && GetHealth() > 0)
	{
		void* tmpPtr = thisEvent->GetParameter2();
		float* tmp = (float*)(tmpPtr);
		SetHealth(GetHealth() - *tmp);

		delete tmp;

		damageEm->Burst();
	}
}

// Shoot the lightning
void SapperBot::LightningBolt(void)
{
	if( Waiting )
		return;

	// Determine the color of the lightning
	unsigned char r = 0, g = 0, b = 0;
	if( CSGD_XAudio2::GetInstance()->SFXIsSoundPlaying(SapSound) )
	{
		r = 100;
		g = 100;
		b = 255;
	}

	else if( CSGD_XAudio2::GetInstance()->SFXIsSoundPlaying(BoltSound) )
		r = 255;
	else
		return;

	CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

	// Draw the lightning effect
	CSGD_Direct3D::GetInstance()->GetLine()->SetWidth(8);

	int camx = GamePlayState::GetInstance()->GetCamX();
	int camy = GamePlayState::GetInstance()->GetCamY();

	CSGD_Direct3D::GetInstance()->DrawLine((int)GetX() - camx + GetWidth()/2,(int)GetY() - camy + GetHeight()/2,
		x1 - camx,y1 - camy,r,g,b);

	CSGD_Direct3D::GetInstance()->DrawLine(x1 - camx,y1 - camy,
		x2 - camx,y2 - camy,r,g,b);

	CSGD_Direct3D::GetInstance()->DrawLine(x2 - camx,y2 - camy,
		(int)GetPlayer()->GetX() - camx + GetPlayer()->GetWidth()/2,(int)GetPlayer()->GetY() - camy + GetPlayer()->GetHeight()/2,r,g,b);
}

// Get the target
Player* SapperBot::GetPlayer(void)
{
	// Find the closest player
	Player* p1 = GamePlayState::GetInstance()->GetPlayer();
	Player* p2 = GamePlayState::GetInstance()->GetPlayer2();
	Player* target = p1;

	if( p2 )
	{
		tVector2D d1, d2;
		d1.fX = GetX() - p1->GetX();
		d1.fY = GetY() - p1->GetY();
		d2.fX = GetX() - p2->GetX();
		d2.fY = GetY() - p2->GetY();
		if( Vector2DLength(d1) > Vector2DLength(d2) )
			target = p2;
	}
	return target;
}